/**
 * Copyright 2011, Under-Ground Studio.
 *  
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *  
 *      http://www.apache.org/licenses/LICENSE-2.0
 *  
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package cn.edu.zju.vlis.aus.activity;

import java.util.ArrayList;
import java.util.List;

import android.app.AlertDialog;
import android.app.Dialog;
import android.app.ListActivity;
import android.content.DialogInterface;
import android.content.SharedPreferences;
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
import android.content.res.Resources;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.text.format.DateFormat;
import android.view.ContextMenu;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.AdapterContextMenuInfo;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.ArrayAdapter;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.ImageView;
import android.widget.Spinner;
import android.widget.TextView;
import cn.edu.zju.vlis.aus.MainActivity;
import cn.edu.zju.vlis.aus.R;
import cn.edu.zju.vlis.aus.bean.UsageRecord;
import cn.edu.zju.vlis.aus.db.UsageRecordDAO;
import cn.edu.zju.vlis.aus.util.AppHelper;
import cn.edu.zju.vlis.aus.util.IconCache;
import cn.edu.zju.vlis.aus.util.IconCache.LoadSingleIconTask;
import cn.edu.zju.vlis.aus.util.PreferenceHelper;

/**
 * Instance of this class is an activity, which display a list of used
 * applications.
 * 
 * @author zll
 * 
 */
public class UsedRankActivity extends ListActivity implements
		OnItemClickListener, OnItemSelectedListener,
		OnSharedPreferenceChangeListener {
	private static final int MENU_ITEM_LAUNCH = 0;
	private static final int MENU_ITEM_UNINSTALL = 1;
	private static final int MENU_ITEM_FILTER = 2;
	private static final int LAUNCH_CONFIRM_DIALOG = 1;
	private LayoutInflater inflater;
	private Spinner rankTypeSpinner;
	private int rankType;

	private List<UsageRecord> rankList;
	private String packageName;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		inflater = LayoutInflater.from(this);
		// set empty view
		View emptyView = inflater.inflate(R.layout.list_empty_view_use_rank,
				null);
		emptyView.setVisibility(View.GONE);
		((ViewGroup) getListView().getParent()).addView(emptyView);
		getListView().setEmptyView(emptyView);
		// set header view
		View headerView = inflater
				.inflate(R.layout.list_header_used_rank, null);
		rankTypeSpinner = (Spinner) headerView
				.findViewById(R.id.rank_type_spinner);
		ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(
				this, R.array.rank_type_array,
				android.R.layout.simple_spinner_item);
		adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
		rankTypeSpinner.setAdapter(adapter);
		rankType = PreferenceHelper.getRankType(this);
		rankTypeSpinner.setSelection(rankType);
		rankTypeSpinner.setOnItemSelectedListener(this);
		getListView().addHeaderView(headerView);
		// set adapter
		createRankList();
		setListAdapter(new UsedRankListAdapter());
		// set on item click listener
		getListView().setOnItemClickListener(this);
		// context menu
		registerForContextMenu(getListView());
	}

	@Override
	protected void onResume() {
		PreferenceHelper.registerOnSharedPreferenceChangeListener(this, this);
		super.onResume();
	}

	@Override
	protected void onPause() {
		PreferenceHelper.unregisterOnSharedPreferenceChangeListener(this, this);
		super.onPause();
	}

	private void createRankList() {
		UsageRecordDAO dao = new UsageRecordDAO(this);
		switch (rankType) {
		case PreferenceHelper.RANK_TYPE_BY_TIME:
			rankList = dao.getRankListByTime();
			break;
		case PreferenceHelper.RANK_TYPE_BY_COUNT:
			rankList = dao.getRankListByCount();
			break;
		case PreferenceHelper.RANK_TYPE_BY_LAST:
			rankList = dao.getRankListByLastUse();
			break;
		}
		dao.close();
	}

	public void setTitleWithCount() {
		String title = getResources().getString(R.string.title_used_rank);
		if (rankList != null) {
			int count = rankList.size();
			StringBuffer titleBuilder = new StringBuffer(title);
			titleBuilder.append('(');
			titleBuilder.append(count);
			titleBuilder.append(')');
			title = titleBuilder.toString();
		}
		MainActivity parent = (MainActivity) getParent();
		parent.setTitle(title);
	}

	@Override
	public void onItemClick(AdapterView<?> parent, View view, int position,
			long id) {
		// get package name for item.
		UsageRecord rec = (UsageRecord) getListAdapter().getItem(position - 1);
		if (rec != null) {
			boolean launchConfirm = PreferenceHelper.getLaunchConfirm(this);
			packageName = rec.getPackageName();
			if (launchConfirm) {
				showDialog(LAUNCH_CONFIRM_DIALOG);
			} else {
				boolean success = AppHelper
						.launchApplication(this, packageName);
				if (!success) {
					refresh();
				}
			}
		}
	}

	@Override
	protected Dialog onCreateDialog(int id) {
		switch (id) {
		case LAUNCH_CONFIRM_DIALOG:
			LayoutInflater inflater = LayoutInflater.from(this);
			View innerDialog = inflater.inflate(R.layout.launch_confirm_dialog,
					null);
			final CheckBox noConfirmCheckBox = (CheckBox) innerDialog
					.findViewById(R.id.no_launch_confirm_checkBox);
			noConfirmCheckBox.setChecked(false);
			return new AlertDialog.Builder(this)
					.setTitle(R.string.launch_confirm_dialog_title)
					.setIcon(android.R.drawable.ic_dialog_alert)
					.setView(innerDialog)
					.setPositiveButton(android.R.string.ok,
							new DialogInterface.OnClickListener() {
								@Override
								public void onClick(DialogInterface dialog,
										int which) {
									if (noConfirmCheckBox.isChecked()) {
										PreferenceHelper.setLaunchComfirm(
												UsedRankActivity.this, false);
									}
									boolean success = AppHelper
											.launchApplication(
													UsedRankActivity.this,
													packageName);
									if (!success) {
										refresh();
									}
								}
							})
					.setNegativeButton(android.R.string.cancel,
							new DialogInterface.OnClickListener() {

								@Override
								public void onClick(DialogInterface dialog,
										int which) {

								}
							}).create();
		}
		return super.onCreateDialog(id);
	}

	@Override
	protected void onPrepareDialog(int id, Dialog dialog) {
		CheckBox noConfirmCheckBox = (CheckBox) dialog
				.findViewById(R.id.no_launch_confirm_checkBox);
		noConfirmCheckBox.setChecked(false);
		super.onPrepareDialog(id, dialog);
	}

	@Override
	public void onItemSelected(AdapterView<?> parent, View view, int position,
			long id) {
		if (rankType != position) {
			rankType = position;
			PreferenceHelper.setRankType(this, position);
			createRankList();
			UsedRankListAdapter listAdapter = (UsedRankListAdapter) getListAdapter();
			listAdapter.notifyDataSetChanged();
		}
	}

	@Override
	public void onNothingSelected(AdapterView<?> parent) {
		// Do nothing.
	}

	@Override
	public void onCreateContextMenu(ContextMenu menu, View v,
			ContextMenuInfo menuInfo) {
		menu.add(Menu.NONE, MENU_ITEM_LAUNCH, 0, R.string.menu_item_launch);
		menu.add(Menu.NONE, MENU_ITEM_UNINSTALL, 1,
				R.string.menu_item_uninstall);
		menu.add(Menu.NONE, MENU_ITEM_FILTER, 2, R.string.menu_item_filter);
	}

	@Override
	public boolean onContextItemSelected(MenuItem item) {
		AdapterContextMenuInfo info = (AdapterContextMenuInfo) item
				.getMenuInfo();
		UsageRecord rec = (UsageRecord) getListAdapter().getItem(
				info.position - 1);
		if (rec != null) {
			String packageName = rec.getPackageName();
			switch (item.getItemId()) {
			case MENU_ITEM_LAUNCH:
				boolean success = AppHelper
						.launchApplication(this, packageName);
				if (!success) {
					refresh();
				}
				break;
			case MENU_ITEM_UNINSTALL:
				AppHelper.uninstallApp(UsedRankActivity.this, packageName);
				// refresh will be called by the MainActivity.onStart()
				break;
			case MENU_ITEM_FILTER:
				rec.setStatistic(false);
				ArrayList<UsageRecord> list = new ArrayList<UsageRecord>();
				list.add(rec);
				UsageRecordDAO dao = new UsageRecordDAO(this);
				dao.updateStatistic(list);
				dao.close();
				MainActivity main = (MainActivity) getParent();
				main.refreshForAppFilter();
				break;
			}
		}
		return super.onContextItemSelected(item);
	}

	@Override
	protected void onDestroy() {
		super.onDestroy();
	}

	public void refresh() {
		UsedRankListAdapter adapter = (UsedRankListAdapter) getListAdapter();
		if (adapter != null) {
			createRankList();
			adapter.notifyDataSetChanged();
		}
	}

	private class UsedRankListAdapter extends BaseAdapter {

		public UsedRankListAdapter() {
		}

		@Override
		public int getCount() {
			if (rankList != null) {
				return rankList.size();
			}
			return 0;
		}

		@Override
		public Object getItem(int position) {
			if (rankList != null) {
				return rankList.get(position);
			} else {
				return null;
			}
		}

		@Override
		public long getItemId(int position) {
			return position;
		}

		@Override
		public View getView(int position, View convertView, ViewGroup parent) {
//			System.out.println("get view for postion "+position);
			View v;
			if (convertView == null) {
				v = inflater.inflate(R.layout.list_item_used_rank, null);
				ViewHolder vh = new ViewHolder();
				vh.iconView = (ImageView) v
						.findViewById(R.id.image_app_icon_used);
				vh.appNameView = (TextView) v
						.findViewById(R.id.text_app_name_used);
				vh.usageView = (TextView) v.findViewById(R.id.text_used);
				vh.lastUseView = (TextView) v.findViewById(R.id.text_last_used);
				vh.btn = (Button) v.findViewById(R.id.btn_shortcut);
				v.setTag(vh);
			} else {
				v = convertView;
			}
			// set the value of each sub view.
			ViewHolder vh = (ViewHolder) v.getTag();
			UsageRecord rec = (UsageRecord) getItem(position);
			Drawable icon = IconCache.getIcon(rec.getPackageName());
			if (icon == null) {
				icon = IconCache.getDefaultIcon();
				new LoadSingleIconTask(UsedRankActivity.this,
						rec.getPackageName(), vh.iconView).execute();
			}
			vh.iconView.setImageDrawable(icon);
			vh.appNameView.setText(rec.getAppName());
			vh.usageView.setText(textUseAssembly(rec.getUseTime(),
					rec.getUseCount()));
			vh.lastUseView.setText(lastUseFormat(rec.getLastUse()));
			vh.btn.setVisibility(View.VISIBLE);
			// set button.
			if (AppHelper.isInstalledShortcut(UsedRankActivity.this,
					rec.getAppName())) {
				vh.btn.setEnabled(false);
				vh.btn.setText(R.string.btn_shortcut_finished);
			} else {
				vh.btn.setEnabled(true);
				vh.btn.setTag(rec.getPackageName());
				vh.btn.setText(R.string.btn_shortcut);
				vh.btn.setOnClickListener(new OnClickListener() {
					@Override
					public void onClick(View v) {
						String packageName = (String) v.getTag();
						if (AppHelper.createShortcut(UsedRankActivity.this,
								packageName)) {
							Button btn = (Button) v;
							btn.setText(R.string.btn_shortcut_finished);
							btn.setEnabled(false);
						}
					}
				});
			}
			return v;
		}

		/**
		 * assemble a String containing how long and how many times this app has
		 * been used.
		 * 
		 * @param useTime
		 *            the seconds of the time
		 * @param useCount
		 *            how many times the app has been used
		 * @return the assembled String of TextUse
		 */
		private String textUseAssembly(int useTime, int useCount) {
			int hours = useTime / 3600;
			useTime = useTime % 3600;
			int minutes = useTime / 60;
			int seconds = useTime % 60;
			Resources r = UsedRankActivity.this.getResources();
			StringBuffer strTime = new StringBuffer(
					getString(R.string.text_use_time_assembly1));
			if (hours != 0) {
				strTime.append(hours
						+ getString(R.string.text_use_time_assembly2));
			}
			if (minutes != 0) {
				strTime.append(minutes
						+ getString(R.string.text_use_time_assembly3));
			}
			if (seconds != 0) {
				strTime.append(seconds
						+ getString(R.string.text_use_time_assembly4));
			}
			String strCount = r.getString(R.string.text_use_count, useCount);
			return strTime.append(strCount).toString();
		}

		private String lastUseFormat(long lastUse) {
			String inFormat = UsedRankActivity.this.getResources().getString(
					R.string.date_format_pattern_last_use);
			String textLastUse = UsedRankActivity.this.getResources()
					.getString(R.string.text_last_use);
			return textLastUse + (String) DateFormat.format(inFormat, lastUse);
		}

		private class ViewHolder {
			private ImageView iconView;
			private TextView appNameView;
			private TextView usageView;
			private TextView lastUseView;
			private Button btn;
		}
	}

	@Override
	public void onSharedPreferenceChanged(SharedPreferences sharedPreferences,
			String key) {
		MainActivity parent = (MainActivity) getParent();
		SettingActivity set = parent.getSettingActivity();
		if (set != null) {
			set.updateLaunchConfirm();
		}
	}
}
